//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.ruoyi.web.core.utils;

import org.apache.tomcat.util.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.InvalidParameterSpecException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

@Component
public class WeChatUtil {
    public static final  String KEY_NAME         = "AES";
    public static final  String CIPHER_ALGORITHM = "AES/CBC/PKCS7Padding";
    private static final Logger log              = LoggerFactory.getLogger(WeChatUtil.class);
    @Value("${weixin.appid}")
    private static       String appId;
    @Value("${weixin.secret}")
    private static       String appSecret;

    public WeChatUtil() {
    }

    public static String getUserInfo(String encryptedData, String sessionKey, String iv) {
        String result   = "";
        byte[] dataByte = Base64.decodeBase64(encryptedData);
        byte[] keyByte  = Base64.decodeBase64(sessionKey);
        byte[] ivByte   = Base64.decodeBase64(iv);

        try {
            int base = 16;
            if (keyByte.length % base != 0) {
                int    groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
                byte[] temp   = new byte[groups * base];
                Arrays.fill(temp, (byte) 0);
                System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
                keyByte = temp;
            }

            Security.addProvider(new BouncyCastleProvider());
            Cipher              cipher     = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
            SecretKeySpec       spec       = new SecretKeySpec(keyByte, "AES");
            AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
            parameters.init(new IvParameterSpec(ivByte));
            cipher.init(2, spec, parameters);
            byte[] resultByte = cipher.doFinal(dataByte);
            if (null != resultByte && resultByte.length > 0) {
                result = new String(resultByte, StandardCharsets.UTF_8);
            }
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidParameterSpecException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        } catch (NoSuchProviderException e) {
            e.printStackTrace();
        }

        return result;
    }

    public static String getSessionKeyAndOpenid(String code) {
        String              requestUrl      = "https://api.weixin.qq.com/sns/jscode2session";
        Map<String, String> requestUrlParam = new HashMap();
        requestUrlParam.put("appid", appId);
        requestUrlParam.put("secret", appSecret);
        requestUrlParam.put("js_code", code);
        requestUrlParam.put("grant_type", "authorization_code");
        return sendPost(requestUrl, requestUrlParam);
    }

    public static String wxDecrypt(String encrypted, String session_key, String iv) {
        String json        = null;
        byte[] encrypted64 = Base64.decodeBase64(encrypted);
        System.out.println("encrypted64:" + encrypted64);
        byte[] key64 = Base64.decodeBase64(session_key);
        System.out.println("key64:" + key64);
        byte[] iv64 = Base64.decodeBase64(iv);
        System.out.println("iv64:" + iv64);

        try {
            init();
            System.out.println("iv64:" + iv64);
            json = new String(decrypt(encrypted64, key64, generateIV(iv64)));
        } catch (Exception e) {
            e.printStackTrace();
        }

        return json;
    }

    public static void init() throws Exception {
        Security.addProvider(new BouncyCastleProvider());
        KeyGenerator.getInstance("AES").init(128);
    }

    public static AlgorithmParameters generateIV(byte[] iv) throws Exception {
        AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
        params.init(new IvParameterSpec(iv));
        return params;
    }

    public static byte[] decrypt(byte[] encryptedData, byte[] keyBytes, AlgorithmParameters iv) throws Exception {
        Key    key    = new SecretKeySpec(keyBytes, "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
        cipher.init(2, key, iv);
        return cipher.doFinal(encryptedData);
    }

    public static String sendPost(String url, Map<String, ?> paramMap) {
        PrintWriter    out    = null;
        BufferedReader in     = null;
        String         result = "";
        String         param  = "";

        for (String key : paramMap.keySet()) {
            param = param + key + "=" + paramMap.get(key) + "&";
        }

        try {
            URL           realUrl = new URL(url);
            URLConnection conn    = realUrl.openConnection();
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("Accept-Charset", "utf-8");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            conn.setDoOutput(true);
            conn.setDoInput(true);
            out = new PrintWriter(conn.getOutputStream());
            out.print(param);
            out.flush();

            String line;
            for (in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8)); (line = in.readLine()) != null; result = result + line) {
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        } finally {
            try {
                if (out != null) {
                    out.close();
                }

                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }

        }

        return result;
    }
}
